/**
 * 
 */
package fr.toussna.dao;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.jdbc.core.RowMapper;

import fr.toussna.entity.Article;
import fr.toussna.entity.Category;
import fr.toussna.entity.DomainEntity;
import fr.toussna.entity.Member;

/**
 * Cette classe est une spécialisation de la classe {@link AbstractDAO}, elle implémente toutes les méthodes abstraites de la classe mère.
 * Elle spécifie les requêtes Sql pour l'entité {@link Article} et rajoutes des méthodes adaptées a la classe Article.
 * 
 * C'est dans cette classe qu'on implémente les algorithmes pour compléter le design pattern Template.
 * 	On utilise le {@link RowMapper} de Spring JDBC pour simplifier le Mapping objet relationnel.
 * 
 * @author My
 * @version 2.0
 *
 */
public class ArticleDAO extends AbstractDAO{
	
	private static final Log LOGGER = LogFactory.getLog(ArticleDAO.class.getName());
	
	// **********************************
	// * Attributs *
	// **********************************
	/**
	 * Nom de la table dans la base
	 */
	private static final String TABLE = "ARTICLE";
	
	/**
	 * Colonne de la table dans la base
	 */
	private static final String COLUMNS = "DATE,CATEGORYID,MEMBERID,AUTOR,TITLE,CONTENT";
	
	// **************************************
	// * Methodes specialles a cette classe *
	// **************************************
	/**
	 * Cette méthode est spécifique aux entités articles, elle permet de sélectionner les articles d'une même catégorie.
	 * 
	 *@param category
	 *					La catégorie d'article
	 *@return La liste des articles de même catégorie 
	 */
	public List<DomainEntity> selectByCategory(Category category){
		List<DomainEntity> list = query(getSelectByCategoryStatement(),new Object[]{category.getId()}, getDomainEntityRowMapper());
		if(LOGGER.isDebugEnabled()){
			LOGGER.debug("Selecting articles by category : "+category.getName()
					+"\n Using statement"+getSelectByCategoryStatement()
					+"\n Received data: "+list.toString()
					);
		}
		return list;
	}
	
	/**
	 * Cette méthode est specifique aux entités articles, elle permet de sélectionner les articles d'un même membre.
	 * 
	 *@param membre
	 *					Le membre propriétaire de l'article
	 *@return La liste des articles de même membre 
	 */
	public List<DomainEntity> selectByMember(Member member){
		List<DomainEntity> list = query(getSelectByMemberStatement(),new Object[]{member.getId()}, getDomainEntityRowMapper());
		if(LOGGER.isDebugEnabled()){
			LOGGER.debug("Selecting articles by member owner : "+member.getName()
					+"\n Using statement"+getSelectByMemberStatement()
					+"\n received data: "+list.toString()
					);
		}
		return list;
	}
	

	// **********************************
	// * Methodes heritees *
	// **********************************
	
	

	@Override
	protected String getSelectSqlStatement() {
		String sql = "SELECT * FROM "+TABLE+" WHERE ID= ?";
		return sql;
	}

	@Override
	protected String getInsertSqlStatement() {
		String sql = "INSERT INTO "+TABLE+" ("+COLUMNS+") VALUES (?,?,?,?,?,?)";
		return sql;
	}

	@Override
	protected String getUpdateSqlStatement() {
		String sql = "UPDATE "+TABLE+" SET DATE= ?, CATEGORYID= ?,MEMBERID= ?,AUTOR= ?,TITLE= ?,CONTENT= ? WHERE ID= ?";
		return sql;
	}

	@Override
	protected String getDeleteSqlStatement() {
		String sql = "DELETE FROM "+TABLE+" WHERE ID= ?";
		return sql;
	}

	@Override
	protected String getSelectAllSqlStatement() {
		String sql = "SELECT * FROM "+TABLE;
		return sql;
	}

	@Override
	protected String getSelectByKeySqlStatement(String key) {
		String sql = "SELECT * FROM "+TABLE+" WHERE TITLE LIKE '%"+key+"%' or AUTOR LIKE '%"+key+"%' or CONTENT LIKE '%"+key+"%'";
		return sql;
	}

	@Override
	protected RowMapper<DomainEntity> getDomainEntityRowMapper() {
		
		return new RowMapper<DomainEntity>() {
		    
			@Override
			public Article mapRow(ResultSet rs, int rowNum) throws SQLException {
				Article article = new Article();
				//DATE,CATEGORYID,MEMBERID,AUTOR,TITLE,CONTENT
				article.setId(rs.getLong("id"));
				article.setDate(rs.getString("date"));
				article.setCategory(new Category(rs.getLong("id")));
				article.setMember(new Member(rs.getLong("id")));
				article.setAutor(rs.getString("autor"));
				article.setTitle(rs.getString("title"));
				article.setContent(rs.getString("content"));
				
				if(LOGGER.isDebugEnabled()){
					LOGGER.debug("Mapped data to entity: "+article.toString());
				}
		           
	            return article;
			}
	    };
	}

	@Override
	protected Object[] getDomainEntityData(DomainEntity entity) {
		Article article = (Article) entity;
		if(article.getId() > 0){
			Object[] obj = new Object[]{article.getDate(),article.getCategory().getId(), article.getMember().getId(),article.getAutor(),article.getTitle(),article.getContent(),article.getId()};
			if(LOGGER.isDebugEnabled()){
				LOGGER.debug("Mapped entity to row data: "+Arrays.toString(obj));
			}
			return obj;
		}else{
			Object[] obj = new Object[]{article.getDate(),article.getCategory().getId(), article.getMember().getId(),article.getAutor(),article.getTitle(),article.getContent()};
			if(LOGGER.isDebugEnabled()){
				LOGGER.debug("Mapped entity to row data: "+Arrays.toString(obj));
			}
			return obj;
		}
	}
	
	// **********************************
	// * Methodes privees *
	// **********************************
	
	private String getSelectByCategoryStatement() {
		String sql = "SELECT * FROM "+TABLE+" WHERE CATEGORYID= ? ";
		return sql;
	}
	
	private String getSelectByMemberStatement() {
		String sql = "SELECT * FROM "+TABLE+" WHERE MEMBERID= ? ";
		return sql;
	}
	
}
